package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.PcMtlAcc;
import com.alks.entity.data.entity.PcMtlCheck;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.PcRtCheckDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.PcRtDetailDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.PcRtLotDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.PcRtUnCheckDto;
import com.alks.function.data.request.stockdept.pcfactorystockwork.RtCheckRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.RtCheckUpRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.RtLotRequest;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcMtlAccMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcMtlCheckMapper;
import com.alks.function.service.stockdept.pcfactorystockquery.IPcMtlReturnService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.ResultCodeEnum.*;

@Service
@Slf4j
public class PcMtlReturnServiceImpl implements IPcMtlReturnService {
    @Autowired
    SD_SQ_PcMtlCheckMapper checkMapper;
    @Autowired
    SD_SQ_PcMtlAccMapper accMapper;


    @Override
    @AutoPageAop
    public ResponseInfo getMtlRtCheckQuery(RtCheckRequest request) {
        /*获取数据*/
        List<PcRtCheckDto> dtos = checkMapper.getMtlRtCheckQuery(request, UserIdThread.get().getCompanyId());
        if (dtos.isEmpty()) {
            return ResponseInfo.ok();
        }
        /*过滤null*/
        Page<PcRtCheckDto> page = (Page<PcRtCheckDto>) dtos;
        dtos = dtos.stream().filter(Objects::nonNull).collect(Collectors.toList());
        int nullCount = (int) dtos.stream().filter(Objects::isNull).count();
        /*封装数据*/
        Map<String,Object> map=new HashMap<>(2);
        map.put("total", page.getTotal()-nullCount);
        map.put("dtos", dtos);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getMtlRtLotQuery(RtLotRequest request) {
        /*获取数据*/
        List<PcRtLotDto> lotDtos = checkMapper.getMtlRtLotQuery(request);
        List<PcRtDetailDto> detailDtos = checkMapper.getMtlRtDetailQuery(request);
        /*求和*/
        double qtyTotal=0;
        double sendTotal=0;
        double unSendTotal=0;
        for (PcRtLotDto dto : lotDtos) {
            qtyTotal+=dto.getQty();
            sendTotal+=dto.getSendQty();
            unSendTotal+=dto.getUnSendQty();
        }
        /*封装数据*/
        Map<String,Object> map =new HashMap<>();
        map.put("qtyTotal",qtyTotal);
        map.put("sendTotal",sendTotal);
        map.put("unSendTotal",unSendTotal);
        map.put("lotDtos",lotDtos);
        map.put("detailDtos",detailDtos);
        return ResponseInfo.ok(map);
    }

    @Override
    @AutoPageAop
    public ResponseInfo getMtlRtUnCheckQuery(RtCheckRequest request) {
        /*获取数据*/
        List<PcRtUnCheckDto> dtos = checkMapper.getMtlRtUnCheckQuery(request);
        if (dtos.isEmpty()) {
            return ResponseInfo.ok();
        }
        Page<PcRtUnCheckDto> page = (Page<PcRtUnCheckDto>) dtos;
        dtos=dtos.stream().filter(Objects::nonNull).collect(Collectors.toList());
        int nullCount = (int) dtos.stream().filter(Objects::isNull).count();
        /*封装数据*/
        Map<String,Object> map = new HashMap<>();
        map.put("total", page.getTotal()-nullCount);
        map.put("dtos", dtos);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getMtlRtBackQuery() {
        String companyId = UserIdThread.get().getCompanyId();
        /*获取数据*/
        List<Map<String, String>> vendor = checkMapper.vendorQuery(companyId);
        List<Map<String, String>> slipType = checkMapper.mtlTypeHeadQuery(null);
        /*封装*/
        Map map = new HashMap();
        map.put("vendor", vendor);
        map.put("slipType", slipType);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo MtlRtCheckUpdate(List<RtCheckUpRequest> request) {
        if (request==null||request.isEmpty()){
            log.warn("请求接口：MtlRtCheckUpdate\n异常原因：输入数据为空");
            return ResponseInfo.error("入参为空", IN_IS_EMPTY.getCode());
        }
        /*判定入参是否正确*/
        for (RtCheckUpRequest rq : request) {
            if ((rq.getSendQty() == null&&rq.getReturnQty()!=null)||
                    (rq.getReturnQty()!=null&&rq.getSendQty() < rq.getReturnQty())) {
                log.error("输入退货数量大于暂存数量，暂存数量：{}，退货数量：{}，PUR_NO：{}"
                        , rq.getSendQty(), rq.getReturnQty(), rq.getPurNo());
                return ResponseInfo.error("存在退货数量大于暂存数量", DATA_IS_ERR.getCode());
            }
        }
        /*更新数据*/
        checkMapper.MtlRtCheckUpdate(request);
        return ResponseInfo.ok("更新成功");
    }

    @Override
    @Transactional
    public ResponseInfo MtlRtPcUpdate(List<RtCheckUpRequest> request) {
        /*判定入参是否正确*/
        for (RtCheckUpRequest rq : request) {
            if (rq.getReturnQty() == null || rq.getReturnQty() == 0) {
                return ResponseInfo.error("退货数量不能为空", DATA_IS_ERR.getCode());
            }
        }
        /*检测库存*/
        String companyId = UserIdThread.get().getCompanyId();
        List<String> mtlNos = request.stream().map(RtCheckUpRequest::getMtlNo).collect(Collectors.toList());
        LambdaQueryWrapper<PcMtlAcc> wrapper=new LambdaQueryWrapper<PcMtlAcc>()
                .select(PcMtlAcc::getMtlNo,PcMtlAcc::getStkQty)
                .eq(PcMtlAcc::getCompanyId, companyId)
                .in(PcMtlAcc::getMtlNo, mtlNos);
        Map<String, BigDecimal> accMap = accMapper.selectList(wrapper).stream()
                .collect(Collectors.toMap(PcMtlAcc::getMtlNo, PcMtlAcc::getStkQty));
        List<String> miss = ArrayUtils.findMiss(accMap.keySet(), mtlNos);
        if (!ArrayUtils.isEmpyt(miss)){
            log.warn("异常接口：MtlRtPcUpdate\n异常原因：【PC_MTL_ACC】无法找到物料：{}",miss);
            return ResponseInfo.error("物料："+miss+"不存在", DATA_IS_ERR.getCode());
        }
        if (ArrayUtils.isEmpyt(mtlNos)){
            log.warn("异常接口：MtlRtPcUpdate\n异常原因：【PC_MTL_ACC】中物料：{}库存不足\n库存没有找到这个物料",request.get(0).getMtlNo());
            return ResponseInfo.error("物料："+request.get(0).getMtlNo()+"库存不足", INPUT_ERROR.getCode());
        }
        for (String mtlNo : mtlNos) {
            BigDecimal sum = request.stream()
                    .filter(rq -> rq.getMtlNo().equals(mtlNo))
                    .map(RtCheckUpRequest::getReturnQty)
                    .map(BigDecimal::valueOf)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);;
            if (accMap.get(mtlNo).compareTo(sum)<0){
                log.warn("异常接口：MtlRtPcUpdate\n异常原因：【PC_MTL_ACC】中物料：{}库存不足\n库存：{}，退货数量：{}",mtlNo,accMap.get(mtlNo),sum);
                return ResponseInfo.error("物料："+mtlNo+"库存不足", INPUT_ERROR.getCode());
            }
        }
        /*补充参数*/
        List<PcMtlCheck> checks = BeanUtil.copyList(request, PcMtlCheck.class);
        LocalDate now = LocalDate.now();
        for (PcMtlCheck check : checks) {
            check.setReturnNo("BFT"+now.format(DateTimeFormatter.ofPattern("yyMM")));
            check.setReturnDate(now.atStartOfDay());
            check.setCompanyId(companyId);
        }
        checkMapper.MtlRtPcUpdate(checks);
        accMapper.MtlRtPcUpdate(request,companyId,now);
        return ResponseInfo.ok("退货批处理成功");
    }


}
